package com.MinesweeperGame.client;


import java.util.HashMap;
import java.util.List;


import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dev.ModuleTabPanel.Session;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.AbsolutePanel;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.MenuBar;
import com.google.gwt.user.client.ui.MenuItem;
import com.google.gwt.user.client.ui.PasswordTextBox;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.PushButton;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextBox;



/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class MinesweeperGame implements EntryPoint {
	
	Label Label_Login = new Label("MINESWEEPER LOGIN");
	Label  Label_UserName = new Label("UserName");
	Label Label_Password = new Label("Password");
	
	TextBox TextBox_UserName = new TextBox();
	PasswordTextBox PasswordTextBox_password = new  PasswordTextBox();
	
	Button Button_Login = new Button("Login",new ClickHandler() {
		
		@Override
		public void onClick(ClickEvent event) {
			
			String uname = TextBox_UserName.getText();
			String pwd = PasswordTextBox_password.getText();
			//removeLogin();

		
			search(uname,pwd);
			System.out.print("hi");
		}
	});
	
	Button Button_Register = new Button("Register",new ClickHandler() {
		
		@Override
		public void onClick(ClickEvent event) {
			
			 registrationForm.show();
		}
	});
	
	PopupPanel PopupPanel_Login;
	
	MinesweeperRegistrationForm registrationForm = new MinesweeperRegistrationForm();
	
	private int _rows = 0;
    private int _cols = 0;
    private int _flags = 10;
    int flag = 0;
    int buttonOpened = 0;
    private int _countBeginner = 0;
    private int _countIntermediate = 0;
    private int _countExpert = 0;
    int no_of_Clicks = 0;
    private String _currentLevel = ""; 
    private String _timerBegginer = "";
    private String _timerIntermediate = "";
    private String _timerExpert = "";
    int click = 0;
    private int _mine;
    
    
    MenuBar mainMenu = new MenuBar();
    MenuBar game = new MenuBar();
    
    
    MenuItem MenuItem_Easy = new MenuItem("Beginner", new Command() {
       
        @Override
        public void execute() {
        	
        	TextBoxBeginner_Timer.setText("");
        	if(_timerBegginer.equals("Running")) {
        		_timeBeginnerTimer.cancel();
        		_countBeginner = 0;
        		
        	}
        
        	flag = 10;
        	_flags = 10;
        	TextBoxFlags.setText(String.valueOf(_flags));
        	
        	TextBoxBeginner_Timer.setVisible(true);
        	TextBoxIntermediate_Timer.setVisible(false);
        	TextBoxExpert_Timer.setVisible(false);
        	TextBoxFlags.setText(String.valueOf(_flags));
        	
        	buttonNewGame.setVisible(true);
        	no_of_Clicks = 0;
        	
        	_currentLevel = "beginner";
        	_timerBegginer = "Running";
        	
            showPanel(10, 10);
        }
    });
   
    MenuItem MenuItem_Medium = new MenuItem("Intermediate",new Command() {
       
        @Override
        public void execute() {
        	
        	TextBoxIntermediate_Timer.setText("");
        	if(_timerIntermediate.equals("Running")) {
        		_timeIntermediateTimer.cancel();
        		_countIntermediate = 0;
        		
        	}
        	 flag = 40;
        	_flags = 40;
        	TextBoxFlags.setText(String.valueOf(_flags));
        	
        	TextBoxBeginner_Timer.setVisible(false);
        	TextBoxIntermediate_Timer.setVisible(true);
        	TextBoxExpert_Timer.setVisible(false);
        	
        	buttonNewGame.setVisible(true);
        	no_of_Clicks = 0;
        	
        	_currentLevel = "intermediate";
        	_timerIntermediate = "Running";
        	
        	_timeBeginnerTimer.cancel();
     
            showPanel(16, 16);
        }
    });
   
   
    MenuItem MenuItem_Difficult = new MenuItem("Expert",new Command() {
       
        @Override
        public void execute() {
        	
        	TextBoxExpert_Timer.setText("");
        	if(_timerExpert.equals("Running")) {
        		_timeExpertTimer.cancel();
        		_countExpert = 0;
        	}
        	
        	TextBoxBeginner_Timer.setVisible(false);
        	TextBoxIntermediate_Timer.setVisible(false);
        	TextBoxExpert_Timer.setVisible(true);
        	
        	flag = 99;
        	_flags = 99;
        	TextBoxFlags.setText(String.valueOf(_flags));
        	
        	buttonNewGame.setVisible(true);
        	no_of_Clicks = 0;
        	
        	_currentLevel = "expert";
        	_timerExpert = "Running";
        	
        	_timeBeginnerTimer.cancel();
        	_timeIntermediateTimer.cancel();

            showPanel(16, 30);
        }
    });
    
   
    MenuItem MenuItem_Highscores = new MenuItem("HighScores",new Command() {
    	
    	  
        @Override
        public void execute() {
        	HighScores highScore = new HighScores();
        	highScore.show();
        	
        }
    });
    
    
    private Timer _timeBeginnerTimer = new Timer() {
         
    	public void run() {
       
    		TextBoxBeginner_Timer.setText(Integer.toString(_countBeginner));
    		_countBeginner++;
    		}
    	};
    
    private Timer _timeIntermediateTimer = new Timer() {
        
        public void run() {
           
            TextBoxIntermediate_Timer.setText(Integer.toString(_countIntermediate));
            _countIntermediate++;
            }
        };
        
        private Timer _timeExpertTimer = new Timer() {
            
            public void run() {
               
                TextBoxExpert_Timer.setText(Integer.toString(_countExpert));
                _countExpert++;
                }
            };
   
	    Label Label_Welcome = new Label(); 
	    TextBox TextBoxBeginner_Timer = new TextBox();
	    TextBox TextBoxIntermediate_Timer = new TextBox();
	    TextBox TextBoxExpert_Timer = new TextBox();
	    TextBox TextBoxFlags = new TextBox();

    
    Button Button_logout = new Button("Logout", new ClickHandler() {
		
		@Override
		public void onClick(ClickEvent event) {
			
			removeGame();
			logout();
			
			RootPanel.get("Div_Main").add(PopupPanel_Login);
	
		}
	});
    
    PushButton buttonNewGame = new PushButton(new Image("smiley.png"),new ClickHandler() {
		
		@Override
    	public void onClick(ClickEvent event) {
			
			TextBoxBeginner_Timer.setText("");
			TextBoxIntermediate_Timer.setText("");
			TextBoxExpert_Timer.setText("");
			
			
			
			TextBoxFlags.setText(String.valueOf(_flags));
			if(_currentLevel.equals("beginner")) {
				buttonNewGame.setVisible(true);
				FlexTable_Mines.clear();
				
				if(_timerBegginer.equals("Running")) {
	        		_timeBeginnerTimer.cancel();
	        		_countBeginner = 0;
	        	}
				no_of_Clicks = 0;
				buttonOpened = 0;
				_flags = 10;
				flag = 10;
				TextBoxFlags.setText(String.valueOf(_flags));
				showPanel(10, 10);

			}
			
			if(_currentLevel.equals("intermediate")) {
				buttonNewGame.setVisible(true);
				
				FlexTable_Mines.clear();
				
				if(_timeIntermediateTimer.equals("Running")) {
	        		_timeIntermediateTimer.cancel();
	        		_countIntermediate = 0;
	        	}
				
				_flags = 40;
				flag = 40;
				TextBoxFlags.setText(String.valueOf(_flags));
				no_of_Clicks = 0;
				showPanel(16, 16);

			}
			
			if(_currentLevel.equals("expert")) {
				
				
				FlexTable_Mines.clear();
				
				if(_timerExpert.equals("Running")) {
	        		_timeExpertTimer.cancel();
	        		_countExpert = 0;
	        	}
				_flags = 99;
				flag =99;
				TextBoxFlags.setText(String.valueOf(_flags));
				no_of_Clicks = 0;
				showPanel(16, 30);

			}
			
		}
	});
   
    FlexTable FlexTable_Mines = new FlexTable();
   
    HashMap< String, MinesweeperButton> mineMap =
        new HashMap<String, MinesweeperGame.MinesweeperButton>();
	
	private final LoginServiceAsync loginService = GWT
			.create(LoginService.class);
	
	 private final GameServiceAsync gameService = GWT
				.create(GameService.class);
	 
	 private final GreetingServiceAsync greetService = GWT
				.create(GreetingService.class);
	 
	
	
	public void onModuleLoad() {
	
		getSessions();
		
		PopupPanel_Login = new PopupPanel();
		
        game.addItem(MenuItem_Easy);
        game.addItem(MenuItem_Medium);
        game.addItem(MenuItem_Difficult);
       

        mainMenu.addItem("Game",game);
        mainMenu.addItem(MenuItem_Highscores);
   
        TextBoxBeginner_Timer.setEnabled(false);
        TextBoxIntermediate_Timer.setEnabled(false); 
        TextBoxExpert_Timer.setEnabled(false);
        
        TextBoxBeginner_Timer.setVisible(false);
        TextBoxIntermediate_Timer.setVisible(false); 
        TextBoxExpert_Timer.setVisible(false);
        
        buttonNewGame.setVisible(false);
        TextBoxFlags.setEnabled(false);
        
        TextBoxBeginner_Timer.setStyleName("textboxTimer");
        TextBoxIntermediate_Timer.setStyleName("textboxTimer");
        TextBoxExpert_Timer.setStyleName("textboxTimer");
        TextBoxFlags.setStyleName("textboxFlag");
        buttonNewGame.setStyleName("buttonNewgame");
        Button_logout.setStyleName("logout");
		
	}
	
	public void loginForm() {
		
		AbsolutePanel absolutePanel=
				new AbsolutePanel();
		
		Label_Login.setStyleName("minesweeperLogin");
		
		absolutePanel.setWidth("200px");
		absolutePanel.setHeight("200px");
		absolutePanel.add(Label_Login);
		
		
		absolutePanel.add(Label_UserName);
		absolutePanel.add(TextBox_UserName);
		
		absolutePanel.add(Label_Password);
		absolutePanel.add(PasswordTextBox_password);
		
		absolutePanel.add(Button_Login);
		absolutePanel.add(Button_Register);
		
		PopupPanel_Login.add(absolutePanel);
		PopupPanel_Login.center();
		RootPanel.get("Div_Main").add(PopupPanel_Login);
		PopupPanel_Login.setStyleName("login");
	
	}
	
	public void game() {
		
		RootPanel.get("Div_Main").remove(PopupPanel_Login); 
		RootPanel.get("Div_Main").add(mainMenu);
        RootPanel.get("Div_Main").add(buttonNewGame);
        RootPanel.get("Div_Main").add(Label_Welcome);
        RootPanel.get("Div_Main").add(TextBoxBeginner_Timer);
        RootPanel.get("Div_Main").add(TextBoxIntermediate_Timer);
        RootPanel.get("Div_Main").add(TextBoxExpert_Timer);
        RootPanel.get("Div_Main").add(TextBoxFlags);
        RootPanel.get("Div_Main").add(Button_logout);
        
       
	}
	
	public void removeGame() {
		
		RootPanel.get("Div_Main").remove(mainMenu);
        RootPanel.get("Div_Main").remove(TextBoxBeginner_Timer);
        RootPanel.get("Div_Main").remove(TextBoxIntermediate_Timer);
        RootPanel.get("Div_Main").remove(TextBoxExpert_Timer);
        RootPanel.get("Div_Main").remove(buttonNewGame);
        RootPanel.get("Div_Main").remove(TextBoxFlags);
        RootPanel.get("Div_Main").remove(Label_Welcome);
        RootPanel.get("Div_Main").remove(FlexTable_Mines);
        RootPanel.get("Div_Main").remove(Button_logout);
        
        
	}
	
	public void addLogin() {
       
	RootPanel.get("Div_Main").add(PopupPanel_Login);
	}
	
	private void getSessions() {
		
		loginService.getSessions(new AsyncCallback<UserInfo>() {
				public void onFailure(Throwable caught) {
					System.out.print("error");
				}
				
				@Override
				public void onSuccess(UserInfo result) {
					
					if(result == null) {
						
						loginForm();
					}
					else {
						Label_Welcome.setText("Welcome   " +result);
						game();
					}
					
				}
			});
		
	}
	
	private void logout() {
		
		loginService.logout(new AsyncCallback<UserInfo>() {
				public void onFailure(Throwable caught) {
					System.out.print("error");
				}
				
				@Override
				public void onSuccess(UserInfo result) {
					
					TextBox_UserName.setText("");
					PasswordTextBox_password.setText("");
					System.out.print("Logout");
				}
			});
		
	}
	
	public void listUsers() {
		
		greetService.listUsers(new AsyncCallback<List<LoginInfo>>() {
			public void onFailure(Throwable caught) {
				System.out.print("error");
			}

			@Override
			public void onSuccess(List<LoginInfo> result) {
				System.out.print("Success");
			}
		});
		
	}

	public void showPanel(int row,int col){
	       
        _rows = row;
        _cols = col;
       
        FlexTable_Mines.clear();

        MinesweeperBackground mineSweeperBackground =
            new MinesweeperBackground(row,col);
       
        for( int i = 0 ; i < _rows ; i++ ) {
           
            for( int j = 0 ; j < _cols ; j++ ) {
               
                boolean isMine =
                    mineSweeperBackground.getIsMine(i, j);
               
                String iString = (new Integer(i)).toString();
                String jString = (new Integer(j)).toString();
               
                if(isMine) {
                   
                    MinesweeperButton someButton =
                        new MinesweeperButton("*",i,j);
                   
                    mineMap.put(iString + "_" + jString, someButton);
                   
                    FlexTable_Mines.setWidget(i, j, someButton);
                   
                  
                 } else {
                     
                     Integer mineNumber =
                         new Integer(mineSweeperBackground.getMineCount(i, j));
                     
                     MinesweeperButton someButton =
                         new MinesweeperButton(mineNumber.toString(),i,j);
                     
                     mineMap.put(iString + "_" + jString, someButton);
                     
                     FlexTable_Mines.setWidget(i, j, someButton);
                     
                    
                 }
            }
        }
       
        mineSweeperBackground.mineMap = mineMap;
       
        RootPanel.get("Div_Main").add(FlexTable_Mines);
    }
	
	public void getScore(){
    	
    	gameService.getScore(new AsyncCallback<List<GameInfo>>() {
				public void onFailure(Throwable caught) {
					System.out.print("error");
				}
				
				@Override
				public void onSuccess(List<GameInfo> result) {
					Window.alert("Score");
					
				}
			});
    	
    }
	
	public void search(String userName, String password) {
		if(TextBox_UserName.getText().equals("")) {
			Window.alert("Enter the UserName");
			}
			else if(PasswordTextBox_password.getText().equals("")) {
				Window.alert("Enter the Password");
			}
		String uname = userName;
		String pwd = password;
		loginService.searchUser(uname,pwd, new AsyncCallback<Boolean>() {
				public void onFailure(Throwable caught) {
					System.out.print("error");
				}
				
				@Override
				public void onSuccess(Boolean result) {
					
					System.out.print(result);
					if(result == true){
						
						game();
					}
					else {
						Window.alert("User Not Found");
					}
				}
			});
	}
	
	 class MinesweeperButton extends Button {
	       
	        private String _text;
	       
	        private int _i;
	       
	        private int _j;
	       
	        private boolean opened = false;
	       
	        public MinesweeperButton(String text, int x, int y) {
	           
	            _text = text;
	            _i= x;
	            _j = y;
	           
	            sinkEvents(Event.ONMOUSEUP | Event.ONDBLCLICK | Event.ONCONTEXTMENU);
	           
	            setStyleName("buttonMinesweeper");
	        }
	       
	        public void onBrowserEvent(Event event) {
	             
	              event.cancelBubble(true);
	              event.preventDefault();
	             
	              switch (DOM.eventGetType(event)) {
	             
	              	case Event.ONMOUSEUP:{

	                    if (DOM.eventGetButton(event) == Event.BUTTON_LEFT) {
	                    	if(event.getAltKey()){
	                    		
	                    		_mine=0;
                        	
                        		check();
		
					System.out.println("mines found :" +_mine);
                           
                            return;
	                    	}
	                    	_timeBeginnerTimer.scheduleRepeating(800);                  	
	                         no_of_Clicks++;
	                         onLeftClick();
	                    }
	                   
	                    if (DOM.eventGetButton(event) == Event.BUTTON_RIGHT) {
	                    	
	                    		click++;
	                    		_flags--;
	                        	TextBoxFlags.setText(String.valueOf(_flags));
	                        	setText("f");
	                    	
	                    	if(_text == "*") {
	                    		
								flag--;
								
	                    	}
	                    	if(flag == 0 && _currentLevel.equals("beginner")) {
	                    		_timeBeginnerTimer.cancel();
	                    		int time = Integer.parseInt(TextBoxBeginner_Timer.getText());
	                    		final Scores score = new Scores(no_of_Clicks,time,_currentLevel);
	                   		
	                    	}
	                    	
	                    	if(flag == 0 && _currentLevel.equals("intermediate")) {
	                            _timeIntermediateTimer.cancel();
	                            int time = Integer.parseInt(TextBoxIntermediate_Timer.getText());
	                            final Scores score = new Scores(no_of_Clicks,time,_currentLevel);
	                          		
	                            	}
	                    	if(flag == 0 && _currentLevel.equals("expert")) {
	                            _timeExpertTimer.cancel();
	                            int time = Integer.parseInt(TextBoxExpert_Timer.getText());
	                            final Scores score = new Scores(no_of_Clicks,time,_currentLevel);
	                           		
	                            	}
	                        	
	                    	onRightClick();
	                    }
	                 
	                    break;
	                  }
	               
	             
	                default:
	                  break;
	              }
	        }
	       
	        private void onLeftClick() {
	           
	        	if(_currentLevel == "beginner") {
	        		_timeBeginnerTimer.scheduleRepeating(800);
	        	}
	        	
	        	if(_currentLevel == "intermediate") {
	        		_timeIntermediateTimer.scheduleRepeating(800);
	        	}
	        	
	        	if(_currentLevel == "expert") {
	        		_timeExpertTimer.scheduleRepeating(800);
	        	}
	        	
	            if(_text.equals("0")){
	        	 
	                openMe();
	                return;
	            }
	           	            
	            if(_text.equals("*") == false) {
	            	
	            	
	            	setText(_text);
	                setEnabled(false);
	                buttonOpened++;
	                System.out.println(buttonOpened);
	             
	            } 
	            
	            if(_text.equals("*")) {
	            
	                openMe();
	                if(_currentLevel.equals("beginner")) {
	                	_timeBeginnerTimer.cancel();
	                	_countBeginner = 0;
	                }
	                if(_currentLevel.equals("intermediate")) {
	                	_timeIntermediateTimer.cancel();
	                	_countIntermediate = 0;
	                }
	                if(_currentLevel.equals("expert")) {
	                	_timeExpertTimer.cancel();
	                	_countExpert = 0;
	                }
	                
	                buttonNewGame.setText(":-(");
	            }
	        }
	       
	        private void onRightClick() {
	    
	        }
	       
	        public void openMe(){
	           
	            if(opened)
	                return;
	           
	            opened  = true;
	           
	            if(_text.equals("*") == false && _text.equals("0") == false) {
	            	
	            	buttonOpened++;
	            	//System.out.println(buttonOpened);
	                setText(_text);
	                setEnabled(false);	
	             
	            } 
	         
	            if(_text.equals("0")) {
	            	
	            	buttonOpened++;
	            	//System.out.println(buttonOpened);
	                checkAround();
	               
	                setEnabled(false);
	            }
	          
	            if(_text.equals("*")) {
	               
	                for( int i = 0 ; i < _rows ; i++ ) {
	                   
	                    for( int j = 0 ; j < _cols ; j++ ) {
	                       
	                        String xString = (new Integer(i)).toString();
	                        String yString = (new Integer(j)).toString();
	                       
	                        mineMap.get(xString + "_" + yString).openMe();
	                       
	                        setEnabled(false);
	                        setText(_text);
	                    }
	                }
	            }
	        }

	public void openAround(){
            
            opened  = true;
          
            if(_text.equals("*") == false && _text.equals("0") == false) {
            	
            		 _buttonOpened++;

                     setText(_text);
                     setEnabled(true);
              
            }
            
            if(_text.equals("*")==true && getText().equals("f")) {
            	
            	_mine++;
            	
            }
           
            if(_text.equals("0")) {
            	
                setEnabled(false);
            }
        } 

		public void check() {
            
            if(_text.equals("*") == true){
            	System.out.println(_text);
                return;
            }
          
            int x = 0;
            int y = 0;
          
            int xMax = _i + 1;
            int yMax = _j + 1;
          
            if(_i > 0){
                x = _i - 1;
            }
          
            if( xMax > _rows - 1){
                xMax = _rows - 1;
            }
          
            if( _j > 0 ){
                y = _j - 1;
            }
          
            if(yMax > _cols - 1){
                yMax = _cols - 1;
            }
            
            for( ; x <= xMax ; x++ ) {
                    
                for( y = (_j > 0)?_j - 1:0 ; y <= yMax ; y++ ) {
                          
                     if( x == _i && y == _j)
                         continue;
                      
                     String xString = (new Integer(x)).toString();
                     String yString = (new Integer(y)).toString();
                        
                     mineMap.get(xString + "_" + yString).openAround();
                     	
                 }
             }
         }
	       
	        public void checkAround() {
	           
	            if(_text.equals("0") == false){
	                return;
	            }
	           
	            int x = 0;
	            int y = 0;
	           
	            int xMax = _i + 1;
	            int yMax = _j + 1;
	           
	            if(_i > 0){
	                x = _i - 1;
	            }
	           
	            if( xMax > _rows - 1){
	                xMax = _rows - 1;
	            }
	           
	            if( _j > 0 ){
	                y = _j - 1;
	            }
	           
	            if(yMax > _cols - 1){
	                yMax = _cols - 1;
	            }
	           
	            for( ; x <= xMax ; x++ ) {
	               
	                for( y = (_j > 0)?_j - 1:0 ; y <= yMax ; y++ ) {
	                       
	                    if( x == _i && y == _j)
	                        continue;
	                   
	                    String xString = (new Integer(x)).toString();
	                    String yString = (new Integer(y)).toString();
	                   
	                    mineMap.get(xString + "_" + yString).openMe();
	                   
	                }
	          }
	     }
	}
}
